<template>
  <div class="category-components component-shop-process-category">
    <div class="content">
      <!-- 左边-全部分类列表 -->
      <div class="left-box">
        <div class="search-box">
          <input
            v-model="categoryName"
            class="search-input"
            :placeholder="$t('publics.categoryInputTips')"
          >
        </div>
        <div
          v-loading="loading"
          element-loading-text="数据处理中..."
        >
          <div
            class="categoryTree-box"
          >
            <el-tree
              ref="categoryTreeRef"
              :data="categorgTreeData"
              node-key="categoryId"
              :filter-node-method="filterNode"
              :props="categoryListTreeProps"
              class="filter-tree"
              show-checkbox
              highlight-current
              :render-after-expand="false"
              icon-class="el-icon-arrow-right"
              :default-expanded-keys="signCategoryParentIds"
              :default-checked-keys="signCategoryIds"
              @check="onCheckChange"
              @node-click="handleNodeClick"
            >
              <template #default="{ node, data }">
                <el-tooltip
                  :content="data.grade === 2 ? data.categoryName + ' ' + data.deductionRate + '%' : data.categoryName"
                  placement="right"
                  effect="light"
                  :show-after="200"
                  class="custom-tree-node"
                >
                  <div
                    class="item-bar"
                  >
                    <div
                      v-rich="filterKey(data, categoryName, node)"
                      class="label"
                    />
                    <div
                      v-if="data.grade === 2"
                      class="unit"
                    >
                      {{ ' ' + data.deductionRate + '%' }}
                    </div>
                  </div>
                </el-tooltip>
              </template>
            </el-tree>
          </div>
        </div>
      </div>

      <!-- 右边-选中类目表格 -->
      <div
        ref="tableBoxRef"
        class="right-box table-box"
      >
        <el-table
          :data="signCategories"
          header-cell-class-name="table-header"
          style="width: 100%"
        >
          <el-table-column
            prop="categoryName"
            :label="$t('shopProcess.categoryName')"
          />
          <el-table-column
            prop="parentName"
            :label="$t('shopProcess.parentCategoryName')"
          />
          <el-table-column
            prop="platformRate"
            :label="$t('shopProcess.categoryRate')"
          >
            <template #default="{ row }">
              <span v-if="row.platformRate || row.platformRate === 0">{{ row.platformRate }} %</span>
              <span v-else>--</span>
            </template>
          </el-table-column>
          <el-table-column
            prop="customizeRate"
            :label="$t('shopProcess.customRate')"
          >
            <template #default="scope">
              <div class="custom-rate">
                <el-input
                  v-model.number="scope.row.customizeRate"
                  :min="0"
                  :max="99.9999"
                  :precision="4"
                  placeholder="0~99.9999"
                  style="width: 80%;"
                  onkeyup="value=value.replace(/[^\d]/g,'')"
                  @blur="checkCustomizeRateInt(scope)"
                />%
              </div>
            </template>
          </el-table-column>
          <el-table-column
            prop="qualifications"
            :label="$t('shopProcess.categoryQualifications')"
            width="200px"
          >
            <template #default="scope">
              <div
                :key="scope.row.qualifications"
                class="business-qual"
              >
                <imgs-upload
                  v-model="scope.row.qualifications"
                  :limit="2"
                  :prompt="false"
                />
              </div>
            </template>
          </el-table-column>
          <el-table-column
            prop="address"
            :label="$t('remindPop.operation')"
            align="center"
          >
            <template #default="scope">
              <el-button
                link
                @click="deleteSelectedCategory(scope)"
              >
                {{ $t('remindPop.delete') }}
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <!-- /右边-选中类目表格 -->
    </div>
  </div>
</template>

<script setup>
import { treeDataTranslate } from '@/utils/index.js'
import { ElMessage } from 'element-plus'

const props = defineProps({
  signCategoryList: {
    type: Array,
    default () {
      return []
    }
  }
})
const emit = defineEmits(['getSignCategoryList'])

const categoryListTreeProps = reactive({
  value: 'categoryId',
  label: 'name'
})

// 已选分类
const signCategories = ref(props.signCategoryList)
// 已选分类列表
watch(() => signCategories.value, () => {
  emit('getSignCategoryList', signCategories.value)
})

const categoryTreeRef = ref(null)
let isChangeVal = false
// 搜索参数
const categoryName = ref('')
watch(() => categoryName.value, (val) => {
  isChangeVal = true
  categoryTreeRef.value?.filter(val)
})

// 已选分类父分类的id set集合
let signCategoryParentIdSet = null
onMounted(() => {
  signCategoryParentIdSet = new Set()
  getPlatformCategory()
  getIds(signCategories.value, 0)
})

// 树形是否初始化完成
let isInitialize = false
let changeValList = []
const filterKey = (data, key, node) => {
  // 获取结点分类名称
  const categoryName = data.categoryName
  if (!isInitialize) {
    // 初始化时默认显示已经勾选的结点，下面代码会影响默认展开的值，因为在第一次初始化时直接返回名称
    return `<span>${categoryName}</span>`
  }
  // 使用changeValList记录已经被标记的node, 避免被多次记录，从而导致鼠标移入移出会自动关闭展开的树节点
  if (!changeValList.some(item => item === node.id)) {
    if (!node.markIsExpanded) {
      // 如果当前结点没有被标记为展开
      node.expanded = false
      changeValList.push(node.id)
    }
  } else {
    if (isChangeVal) {
      changeValList = []
      isChangeVal = false
    }
  }
  const ind = categoryName.indexOf(key)
  if (ind !== -1 && key !== '') {
    // 当前结点匹配到关键词
    if (!node.markIsExpanded) {
      if (node.parent && !node.parent.markIsExpanded) {
        node.parent.expanded = true
        node.parent.markIsExpanded = true
        if (node.parent.parent && !node.parent.parent.markIsExpanded) {
          node.parent.parent.expanded = true
          node.parent.parent.markIsExpanded = true
        }
      }
    }
    // 高亮关键词
    return (
      categoryName.split('').slice(0, ind).join('') + "<span style='color: coral'>" + key + '</span>' + categoryName.split('').slice(ind + key.length).join('')
    )
  } else {
    // 当前结点没有匹配到关键词或者用户输入为空时，直接返回名称
    return `<span>${categoryName}</span>`
  }
}

const loading = ref(false)
// 平台分类
let patformCategories = []
// 全部分类
const categorgTreeData = ref([])
/**
 * 获取平台分类列表，并转换成树形结构
 */
const getPlatformCategory = () => {
  http({
    url: http.adornUrl('/prod/category/listCategory'),
    method: 'get',
    params: http.adornParams({
      maxGrade: 2
    })
  }).then(({ data }) => {
    // 过滤下线分类
    data = data.filter(el => el.status !== 0)
    loading.value = false
    patformCategories = data
    let categorgTreeDataPar = treeDataTranslate(data, 'categoryId', 'parentId')
    // 过滤没有下级分类的类目
    categorgTreeDataPar = removeNotThirdCategoryItem(categorgTreeDataPar)
    categorgTreeData.value = categorgTreeDataPar
  })
}

// 已选分类id数组
const signCategoryIds = ref([])
// 已选分类父分类id数组
const signCategoryParentIds = ref([])
const getIds = (data, sts) => {
  signCategoryIds.value.splice(0, signCategoryIds.value.length)
  signCategoryParentIds.value.splice(0, signCategoryParentIds.value.length)
  data.forEach(el => {
    // 已选分类id
    signCategoryIds.value.push(el.categoryId)
    // 已选分类的父分类id
    signCategoryParentIdSet.add(el.parentId)
  })
  signCategoryParentIds.value = Array.from(signCategoryParentIdSet)
  if (sts === 1) {
    nextTick(() => {
      categoryTreeRef.value?.setCheckedKeys(signCategoryIds.value)
    })
  }
}

/**
 * 搜索结点，该方法只起标记作用，
 */
// eslint-disable-next-line no-unused-vars
const filterNode = (value, data, node) => {
  isInitialize = true
  node.markIsExpanded = false
  return true
}

/**
 * 去除没有三级分类的类目
 */
const removeNotThirdCategoryItem = (treeData) => {
  const firstCategory = treeData
  const length = firstCategory.length
  for (let i = 0, index = 0; i < length; i++) {
    if (firstCategory[index].grade !== 2) {
      if (firstCategory[index].children && firstCategory[index].children !== undefined && (firstCategory[index].children.some(item => item.children) || firstCategory[index].grade !== 0)) {
        const secondCategory = firstCategory[index].children
        firstCategory[index].children = removeNotThirdCategoryItem(secondCategory)
      } else {
        firstCategory.splice(index, 1)
        // 当前位置的元素已经被删除，当前位置索引不用++
        continue
      }
    }
    index++
  }
  return firstCategory
}

let message = false
/**
 * 对勾选到的数据逐一处理
 * @param nodeObj 节点数据
 * @param isExist 是否为选中状态
 * @returns {Promise<void>}
 */
const onCheckLevel = async (nodeObj, isExist) => {
  const isExistTwo = props.signCategoryList.some(item => item.categoryId === nodeObj.categoryId)
  if (nodeObj.grade !== 2) {
    return
  }

  if (isExist) {
    if (signCategories.value.length === 200) {
      if (!message) {
        message = true
        ElMessage({
          message: $t('shopProcess.categoryAddMaxLimitTips'),
          type: 'error',
          duration: 1000,
          onClose: () => {
            message = false
          }
        })
      }
      getIds(signCategories.value, 1)
      return
    }
    if (isExistTwo) {
      return
    }
    const signCategory = {
      categoryId: nodeObj.categoryId,
      categoryName: nodeObj.categoryName,
      parentName: nodeObj.parentName || '',
      platformRate: nodeObj.deductionRate,
      categoryStatus: nodeObj.status,
      parentId: nodeObj.parentId,
      qualifications: ''
    }
    if (!nodeObj.parentName) {
      patformCategories.some(el => {
        if (el.categoryId === nodeObj.parentId) {
          signCategory.parentName = el.categoryName
          return true
        }
        return false
      })
    }
    signCategories.value.push(signCategory)
    signCategoryParentIdSet.add(nodeObj.parentId)
  } else {
    signCategories.value = deleteById(nodeObj.categoryId, signCategories.value)
  }
}

/**
 * 将勾选到的数据进行遍历
 * @param nodeObj 勾选到的当前节点数据
 * @param isExist 判断是否为选中状态
 * @returns {Promise<void>}
 */
const onHandleCheck = async (nodeObj, isExist) => {
  await onCheckLevel(nodeObj, isExist)
  if (nodeObj.children && nodeObj.children.length > 0) {
    for (const item of nodeObj.children) {
      await onCheckLevel(item, isExist)
      if (item.children && item.children.length > 0) {
        for (const childItem of item.children) {
          if (props.signCategoryList.length >= 200 && isExist) {
            await getIds(props.signCategoryList, 1)
            return
          }
          await onCheckLevel(childItem, isExist)
        }
      }
    }
  }
}

/**
 * 节点选中状态发生变化时的回调
 * @param {Object} nodeObj 传递给 data 属性的数组中该节点所对应的对象
 * @param {Boolean} nodeStatus 树目前的选中状态对象
 */
const onCheckChange = async (nodeObj, nodeStatus) => {
  const isExist = nodeStatus.checkedKeys.includes(nodeObj.categoryId)
  if (nodeObj.grade !== 2 && props.signCategoryList.length >= 200 && isExist) {
    ElMessage({
      message: $t('shopProcess.categoryAddMaxLimitTips'),
      type: 'error',
      duration: 1000
    })
    await getIds(props.signCategoryList, 1)
    return
  }
  if (nodeObj.grade === 2) {
    await onHandleCheck(nodeObj, isExist)
    return
  }
  loading.value = true
  setTimeout(() => {
    onHandleCheck(nodeObj, isExist).then(() => {
      loading.value = false
    })
  }, 200)
}

/**
 * 根据id删除数组项
 * @param {Number} id 需要删除的id
 * @param {Array} list 目标数组
 * @return {Array}
 */
const deleteById = (id, list) => {
  for (let index = list.length - 1; index >= 0; index--) {
    if (list[index] && list[index].categoryId === id) {
      list.splice(index, 1)
    }
  }
  return list
}

/**
 * 删除已选分类
 */
const deleteSelectedCategory = (scope) => {
  const index = scope.$index
  signCategories.value.splice(index, 1)
  getIds(signCategories.value, 1)
}

/**
 * 自定义扣率输入框判断
 */
const checkCustomizeRateInt = (scope) => {
  const { row, $index } = scope
  const customizeRate = parseFloat(row.customizeRate)
  if (customizeRate || customizeRate === 0) {
    const reg = /^(([1-9]{0,1}?\d{1}?)|(0{1}))(\.\d{0,4})?$/
    if (!reg.test(customizeRate)) {
      signCategories.value[$index].customizeRate = ''
      ElMessage({
        message: $t('shopProcess.customizeRateErrorTips'),
        type: 'error',
        duration: 2000
      })
    }
    if (customizeRate === 0) {
      signCategories.value[$index].customizeRate = 0
    }
  }
}
const handleNodeClick = (nodeObj, nodeStatus) => {
  if (nodeStatus.level !== 3) return
  let keys = signCategories.value.map(item => item.categoryId)
  if (nodeStatus.checked) {
    for (let i = 0; i < keys.length; i++) {
      if (keys[i] === nodeObj.categoryId) {
        signCategories.value = signCategories.value.filter(item => item.categoryId !== nodeObj.categoryId)
        keys.splice(i, 1)
        break
      }
    }
  } else {
    if (signCategories.value.length + props.signingCount >= 200) {
      ElMessage({
        message: $t('shopProcess.categoryAddMaxLimitTips'),
        type: 'error',
        duration: 1000
      })
    } else {
      const signCategory = {
        categoryId: nodeObj.categoryId,
        categoryName: nodeObj.categoryName,
        parentName: nodeObj.parentName || '',
        platformRate: nodeObj.deductionRate,
        categoryStatus: nodeObj.status,
        parentId: nodeObj.parentId,
        qualifications: ''
      }
      if (!nodeObj.parentName) {
        patformCategories.some(el => {
          if (el.categoryId === nodeObj.parentId) {
            signCategory.parentName = el.categoryName
            return true
          }
          return false
        })
      }
      signCategories.value.push(signCategory)
      keys = keys.concat(nodeObj.categoryId)
    }
  }
  categoryTreeRef.value?.setCheckedKeys(keys)
}

</script>

<style lang="scss" scoped>
@use "index";
</style>
